﻿using System;
using System.Windows;
using System.Windows.Forms;
using System.IO;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Montador;
namespace Montador.Tests
{
    [TestClass()]
    public class UnitTest1
    {
    }
}

namespace UnitTestProject1
{
    [TestClass()]
    public class UnitTest1
    {
        Montador.Montador MON;
        OpcMont OPS;

        [TestInitialize()]
        public void PreCreateMontador()
        {
            OPS = new OpcMont();
            OPS.Debug = false;
            MON = null;

            // Test Source Files are part of the UnitTestProject1 and have the CopyToOutput property
        }



        [TestCleanup()]
        public void DiscardMontador()
        {
            MON = null;
        }

        [TestMethod()]
        public void MontadorTest()
        {
            // unidentified processor error will be discovered in IDE tests
            MON = new Montador.Montador("Does not exist");  
            Assert.IsNotNull(MON, "Constructor of Montador did not produce an object");
        }

        [TestMethod()]
        public void NovoProgTest()
        {
            // unidentified processor error will be discovered in IDE tests
            MON = new Montador.Montador(null);
            MON.NovoProg();
            Assert.IsNotNull(MON.PROG, "NovoProg failed to instanciate program object.");
        }

        [TestMethod()]
        public void DescartarProgTest()
        {
            // unidentified processor error will be discovered in IDE tests
            MON = new Montador.Montador(null);
            MON.NovoProg();
            MON.DescartarProg();
            Assert.IsNull(MON.PROG, "DescartarProg failed to erase program object.");
        }

        [TestMethod()]
        public void LerProgTest()
        {
            MON = new Montador.Montador(null);  // processor identity will be provided by source file

            // breakpoints are being ignored. Unit testing sucks. Need to continue in new VS instance :-(
            //System.Diagnostics.Debugger.Break();

            // Test Source Files are part of the UnitTestProject1 and have the CopyToOutput property
            FileStream fsFonte = new FileStream(@"NOP.mn5", FileMode.Open);
            BinaryReader brFonte = new BinaryReader(fsFonte);
            MON.LerProg(brFonte);

            MON.DescartarProg();
            fsFonte = new FileStream(@"ProcessadorInexistente.mn5", FileMode.Open);
            brFonte = new BinaryReader(fsFonte);
            try
            {
                MON.LerProg(brFonte);
                Assert.Fail("Source program contains illegal processor, LerProg should have failed.");
            }
            catch (ApplicationException) { } // when illegal processor found

        }

        [TestMethod()]
        public void BasicAssemblyTest()
        {
            // testing the basics of assembling. Needs only NOP, JMP, ADD, .org. and .external

            MON = new Montador.Montador(null);  // processor identity will be provided by source file

            // funciona em geral?
            AssembleProg("NOP.mn5", 0);

            // descobre erros simples?
            AssembleProg("IllegalOpcode.mn5", 1);
            AssembleProg("IllegalDirective.mn5", 1);
            AssembleProg("UndefinedLabel.mn5", 1);

            AssembleProg("JMP_GT_64K.mn5", 1);
            AssembleProg("JMP_GT_4G.mn5", 1);
            AssembleProg("ORG_GT_64K.mn5", 1);
            AssembleProg("ORG_GT_4G.mn5", 1);

            // mexe com rótulos locais, símbolos e fixups?
            AssembleProg("JMP_Local.mn5", 0);
        }

        private void LerProg(string prmProg)
        {
            // read a source program from the deployment directory
            // Adding new source files to the test project and putting CopyIfNewer to the properties is required.
            FileStream fsFonte = new FileStream(prmProg, FileMode.Open);
            BinaryReader brFonte = new BinaryReader(fsFonte);
            MON.DescartarProg();
            MON.LerProg(brFonte);
        }
        private void AssembleProg(string prmProg, UInt32 numErr)
        {
            // read a source program from deployment folder, assemble it and count the errors
            LerProg(prmProg);
            MON.Montar(OPS);
            Assert.AreEqual(MON.NumErros, numErr, 
                String.Format("Montar must assemble program {0} with {1} errors but found {2}.",
                prmProg, numErr, MON.NumErros));
        }
    }
}

